import {
  Injectable,
  HttpStatus,
  HttpException,
  UnauthorizedException,
  Inject,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { RegisterDto } from './dto/register.dto';
import { LoginDto } from './dto/login.dto';
import { ForgotPasswordDto } from './dto/forgot-password.dto';
import { UserInfoDto } from './dto/user-info.dto';
import { User } from './entities/user.entity';
import { ApiResponseDto } from '../common/dto/api-response.dto';
import { LoggerService } from '../common/logger/logger.service';
import * as bcrypt from 'bcrypt';

@Injectable()
export class AuthService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
    private jwtService: JwtService,
    private logger: LoggerService,
  ) {
    this.logger.setContext('AuthService');
  }

  // 注册
  async register(registerDto: RegisterDto): Promise<ApiResponseDto<any>> {
    this.logger.log(`开始注册用户: ${registerDto.username}`);

    if (registerDto.password !== registerDto.confirmPassword) {
      this.logger.warn(
        `用户注册失败: ${registerDto.username} - 两次输入的密码不一致`,
      );
      return ApiResponseDto.error('两次输入的密码不一致');
    }
    //用户名由字母开头，只能含有字母、数字或者下划线
    if (!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(registerDto.username)) {
      this.logger.warn(
        `用户注册失败: ${registerDto.username} - 用户名格式不正确`,
      );
      return ApiResponseDto.error(
        '用户名由字母开头，只能含有字母、数字或者下划线',
      );
    }
    // 邮箱已被注册
    const existingEmail = await this.usersRepository.findOne({
      where: { email: registerDto.email },
    });
    if (existingEmail) {
      this.logger.warn(`用户注册失败: ${registerDto.username} - 邮箱已被注册`);
      return ApiResponseDto.error('该邮箱已被注册');
    }
    // 用户名已存
    const existingUser = await this.usersRepository.findOne({
      where: { username: registerDto.username },
    });
    if (existingUser) {
      this.logger.warn(`用户注册失败: ${registerDto.username} - 用户名已存在`);
      return ApiResponseDto.error('用户名已存在');
    } else {
      const hashedPassword = await bcrypt.hash(registerDto.password, 10); // 哈希密码
      const user = new User();
      user.username = registerDto.username;
      user.email = registerDto.email;
      user.password = hashedPassword;
      user.nickname = registerDto.username; // 默认使用用户名作为昵称
      user.signature = ''; // 默认空签名
      user.description = ''; // 默认空简介
      user.avatar = ''; // 默认空头像

      const savedUser = await this.usersRepository.save(user);

      // 移除敏感信息
      const { password, ...result } = savedUser;

      this.logger.log(`用户注册成功: ${registerDto.username}`);
      return ApiResponseDto.created(result, '注册成功');
    }
  }

  // 登录
  async login(loginDto: LoginDto): Promise<ApiResponseDto<any>> {
    this.logger.log(`尝试登录: ${loginDto.username}`);

    try {
      const user = await this.usersRepository.findOne({
        where: { username: loginDto.username },
      });

      if (!user) {
        this.logger.warn(`登录失败: ${loginDto.username} - 用户不存在`);
        return ApiResponseDto.error('用户名不存在', HttpStatus.UNAUTHORIZED);
      }

      const isPasswordValid = await bcrypt.compare(
        loginDto.password,
        user.password,
      );

      if (!isPasswordValid) {
        this.logger.warn(`登录失败: ${loginDto.username} - 密码错误`);
        return ApiResponseDto.error('密码错误', HttpStatus.UNAUTHORIZED);
      }

      const payload = { username: user.username, sub: user.id };
      const token = this.jwtService.sign(payload);

      this.logger.log(`登录成功: ${loginDto.username}`);
      return ApiResponseDto.success(
        {
          access_token: token,
          user_id: user.id,
          username: user.username,
        },
        '登录成功',
      );
    } catch (error) {
      this.logger.error(`登录过程异常: ${loginDto.username}`, error.stack);
      throw new HttpException(
        '登录过程中发生错误',
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  //找回密码
  async forgotPassword(
    forgotPasswordDto: ForgotPasswordDto,
  ): Promise<ApiResponseDto<any>> {
    const user = await this.usersRepository.findOne({
      where: { email: forgotPasswordDto.email },
    });
    if (!user) {
      return ApiResponseDto.error('邮箱不存在');
    }
    // 这里应该实现发送重置密码邮件的逻辑
    return ApiResponseDto.success(null, '重置密码的邮件已发送，请查收');
  }

  // 根据token获取用户信息
  async getUserInfo(token: string): Promise<ApiResponseDto<any>> {
    try {
      // 验证并解析 token
      const decoded = this.jwtService.verify(token);

      // 从数据库获取用户信息
      const user = await this.usersRepository.findOne({
        where: { id: decoded.sub },
      });

      if (!user) {
        return ApiResponseDto.notFound('用户不存在');
      }

      // 移除敏感信息
      const { password, ...result } = user;

      return ApiResponseDto.success(result, '用户信息获取成功');
    } catch (error) {
      throw new UnauthorizedException('无效的令牌或令牌已过期');
    }
  }

  // 更新用户信息
  async updateUserInfo(
    token: string,
    userInfoDto: UserInfoDto,
  ): Promise<ApiResponseDto<any>> {
    try {
      // 验证并解析 token
      const decoded = this.jwtService.verify(token);

      // 从数据库获取用户信息
      const user = await this.usersRepository.findOne({
        where: { id: decoded.sub },
      });

      if (!user) {
        return ApiResponseDto.notFound('用户不存在');
      }

      // 更新用户信息
      if (userInfoDto.nickname) {
        user.nickname = userInfoDto.nickname;
      }
      if (userInfoDto.signature) {
        user.signature = userInfoDto.signature;
      }
      if (userInfoDto.description) {
        user.description = userInfoDto.description;
      }
      if (userInfoDto.avatar) {
        user.avatar = userInfoDto.avatar;
      }

      // 保存用户信息到数据库
      await this.usersRepository.save(user);

      // 移除敏感信息
      const { password, ...result } = user;

      return ApiResponseDto.success(result, '用户信息更新成功');
    } catch (error) {
      throw new UnauthorizedException('无效的令牌或令牌已过期');
    }
  }
}
